package com.mjk.common.core.jdbc.util;


import cn.hutool.core.annotation.AnnotationUtil;
import com.mjk.common.base.model.BaseEntity;
import com.mjk.common.core.jdbc.annotation.ArcSharding;
import com.mjk.common.core.jdbc.annotation.ArcShardingProxy;
import com.mjk.common.core.jdbc.service.plus.constns.BeeTypeEntity;
import com.mjk.common.core.jdbc.service.plus.provider.BeeDataSourceType;
import com.mjk.common.core.jdbc.service.plus.provider.interfaces.IBeeTypeMapping;
import com.mjk.common.core.jdbc.sphere.StrategyEnum;
import com.mjk.common.tools.logger.BizLogger;
import com.mjk.common.util.ObjectUtils;
import org.apache.ibatis.type.JdbcType;

import java.lang.annotation.Annotation;
import java.lang.reflect.Proxy;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Locale;

/**
 * ArcSharding 操作工具类
 */
public class ShardingUtils {

    /**
     * 获取ArcSharding
     *
     * @param entity
     * @return
     */
    public static ArcSharding getArcSharding(BaseEntity entity) {
        return getArcSharding(entity.getClass());
    }

    public static ArcSharding getArcSharding(Class<? extends BaseEntity> clazz) {
        ArcSharding arc = clazz.getAnnotation(ArcSharding.class);
        ArcShardingProxy proxy = clazz.getAnnotation(ArcShardingProxy.class);
        if (null == arc && proxy != null) {
            arc = clazz.getSuperclass().getAnnotation(ArcSharding.class);
            return deepCopyArcSharding(arc, proxy);
        }
        return arc;
    }

    /**
     * 深拷贝 arcsharing
     *
     * @param arc
     * @param proxy
     * @return
     */
    public static ArcSharding deepCopyArcSharding(ArcSharding arc, ArcShardingProxy proxy) {
        ArcSharding copiedArc = new ArcSharding() {
            @Override
            public Class<? extends Annotation> annotationType() {
                return ArcSharding.class;
            }

            @Override
            public String userName() {
                return ObjectUtils.isEmpty(proxy.userName()) ? arc.userName() : proxy.userName();
            }

            @Override
            public String table() {
                return ObjectUtils.isEmpty(proxy.table()) ? arc.table() : proxy.table();
            }

            @Override
            public String key() {
                return arc.key();
            }

            @Override
            public String subKey() {
                return arc.subKey();
            }

            @Override
            public String concatChar() {
                return arc.concatChar();
            }

            @Override
            public StrategyEnum strtegy() {
                return arc.strtegy();
            }

            @Override
            public int shardingNum() {
                return arc.shardingNum();
            }

            @Override
            public boolean hump() {
                return arc.hump();
            }

            @Override
            public String dataSource() {
                return ObjectUtils.isEmpty(proxy.dataSource()) ? arc.dataSource() : proxy.dataSource();
            }
        };

        return copiedArc;
    }

    /**
     * 根据数据库返回的 resultset 创建实体类
     * @param rs
     * @param entity
     * @param sharding
     * @return
     * @throws SQLException
     */
    public static String getModel(ResultSet rs, BaseEntity entity, ArcSharding sharding) throws SQLException {
        StringBuilder modelStr = new StringBuilder("package " + entity.getClass().getPackage().getName() + ";\n" + "\n"
                + "import com.mjk.common.base.model.BaseEntity;\n"
                + "import com.mjk.common.core.jdbc.annotation.ArcSharding;\n"
                + "import com.mjk.common.core.jdbc.annotation.ExampleField;\n"
                + "import com.mjk.common.core.jdbc.annotation.Filed;\n"
                + "import com.mjk.common.core.jdbc.annotation.Id;\n" + "import lombok.Data;\n" + "\n" +

                "@Data\n" + "@ArcSharding(dataSource = \"" + sharding.dataSource() + "\", table = \"" + sharding.table() + "\",userName=\"" + sharding.userName() + "\""
                + ")\n" + "public class " + entity.getClass().getSimpleName()
                + " extends BaseEntity {\n");

        while (rs.next()) {
            String columnName = rs.getString("COLUMN_NAME");
            int dataType = rs.getInt("DATA_TYPE");//对应的jdbctype
            String remark = rs.getString("REMARKS");
            int lenght = rs.getInt("COLUMN_SIZE");
            if (columnName.equalsIgnoreCase("id")) {
                modelStr.append("\n").append("    @Id\n").append("    @ExampleField\n").append("    private Integer id;\n");
            } else {
                try {
                    //如果columnName 首字母大写，需要转为小写
                    columnName = columnName.substring(0, 1).toLowerCase(Locale.ENGLISH) + columnName.substring(1);
                    IBeeTypeMapping mapping = BeeDataSourceType.getMapping(entity);
                    //Set<BeeTypeEntity> entities = Objects.requireNonNull(mapping).getMapping();
                    BeeTypeEntity type = mapping.getTypeByJdbcType(JdbcType.forCode(dataType));
                    modelStr.append("    @Filed(comment = \"").append(remark).append("\",lenght = ").append((lenght < 0) ? type.getLenght() : lenght).append(",cloum = \"").append(columnName).append("\")\n").append("    private ").append(type.getJavaType()).append(" ").append(columnName).append(";\n");
                } catch (Exception e) { //如果抛异常 打印出对用的datetype
                    BizLogger.error("dataType in mapping is null:" + dataType);
                }
            }
        }
        modelStr.append("\n").append("}");
        return modelStr.toString();
    }
}